package com.foohoo.benchmark.string;

import lombok.extern.slf4j.Slf4j;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;

import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 测试包装类型转String的几种方法的性能
 * Benchmark                                Mode  Cnt    Score     Error  Units
 * WrapperClass2String.booleanWithPlus      avgt    3   22.197 ±  30.739  ns/op
 * WrapperClass2String.booleanWithStringOf  avgt    3    4.029 ±   1.914  ns/op
 * WrapperClass2String.booleanWithToString  avgt    3    3.903 ±   1.888  ns/op
 * WrapperClass2String.doubleWithPlus       avgt    3  445.621 ± 308.750  ns/op
 * WrapperClass2String.doubleWithStringOf   avgt    3  333.983 ± 236.303  ns/op
 * WrapperClass2String.doubleWithToString   avgt    3  355.805 ± 202.901  ns/op
 * WrapperClass2String.floatWithPlus        avgt    3  153.660 ± 113.088  ns/op
 * WrapperClass2String.floatWithStringOf    avgt    3  122.698 ± 103.361  ns/op
 * WrapperClass2String.floatWithToString    avgt    3  118.244 ±  18.940  ns/op
 * WrapperClass2String.integerWithPlus      avgt    3   61.187 ±  36.363  ns/op
 * WrapperClass2String.integerWithStringOf  avgt    3   53.053 ±  23.114  ns/op
 * WrapperClass2String.integerWithToString  avgt    3   49.543 ±   6.378  ns/op
 * WrapperClass2String.longWithPlus         avgt    3   81.354 ±  34.058  ns/op
 * WrapperClass2String.longWithStringOf     avgt    3   66.604 ±   6.350  ns/op
 * WrapperClass2String.longWithToString     avgt    3   73.674 ± 304.981  ns/op
 * 一句话结论: 对于基础包装类型转字符串，toString和String.valueOf最快;其中String.valueOf用的也是toString实现但是多了一个判空;plus运算符其实是构建了一个StringBuilder
 *
 * @author mzdbxqh
 * @date 2020-10-26 13:35
 **/
@Slf4j
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 3, time = 1)
@Fork(1)
@Threads(1)
@State(Scope.Benchmark)
public class WrapperClass2String {

	private Integer primitiveTypeOfInteger;
	private Long primitiveTypeOfLong;
	private Float primitiveTypeOfFloat;
	private Double primitiveTypeOfDouble;
	private Boolean primitiveTypeOfBoolean;

	@Setup(Level.Trial)
	public void initialize() {
		Random random = new Random();
		primitiveTypeOfInteger = random.nextInt();
		primitiveTypeOfLong = random.nextLong();
		primitiveTypeOfFloat = random.nextFloat();
		primitiveTypeOfDouble = random.nextDouble();
		primitiveTypeOfBoolean = random.nextBoolean();
	}

	@Benchmark
	public void integerWithToString(Blackhole bh) {
		bh.consume(primitiveTypeOfInteger.toString());
	}

	@Benchmark
	public void integerWithPlus(Blackhole bh) {
		bh.consume(primitiveTypeOfInteger + "");
	}

	@Benchmark
	public void integerWithStringOf(Blackhole bh) {
		bh.consume(String.valueOf(primitiveTypeOfInteger));
	}

	@Benchmark
	public void longWithToString(Blackhole bh) {
		bh.consume(primitiveTypeOfLong.toString());
	}

	@Benchmark
	public void longWithPlus(Blackhole bh) {
		bh.consume(primitiveTypeOfLong + "");
	}

	@Benchmark
	public void longWithStringOf(Blackhole bh) {
		bh.consume(String.valueOf(primitiveTypeOfLong));
	}

	@Benchmark
	public void floatWithToString(Blackhole bh) {
		bh.consume(primitiveTypeOfFloat.toString());
	}

	@Benchmark
	public void floatWithPlus(Blackhole bh) {
		bh.consume(primitiveTypeOfFloat + "");
	}

	@Benchmark
	public void floatWithStringOf(Blackhole bh) {
		bh.consume(String.valueOf(primitiveTypeOfFloat));
	}

	@Benchmark
	public void doubleWithToString(Blackhole bh) {
		bh.consume(primitiveTypeOfDouble.toString());
	}

	@Benchmark
	public void doubleWithPlus(Blackhole bh) {
		bh.consume(primitiveTypeOfDouble + "");
	}

	@Benchmark
	public void doubleWithStringOf(Blackhole bh) {
		bh.consume(String.valueOf(primitiveTypeOfDouble));
	}

	@Benchmark
	public void booleanWithToString(Blackhole bh) {
		bh.consume(primitiveTypeOfBoolean.toString());
	}

	@Benchmark
	public void booleanWithPlus(Blackhole bh) {
		bh.consume(primitiveTypeOfBoolean + "");
	}

	@Benchmark
	public void booleanWithStringOf(Blackhole bh) {
		bh.consume(String.valueOf(primitiveTypeOfBoolean));
	}
}
